﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.ServiceModel.DomainServices.Client;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Shapes;
using AppShare.Data.Models;
using AppShare.Web;

namespace AppShare
{
    public partial class Calc : Page
    {
        private IList<OperationBase> possiblyPendingOperations = new List<OperationBase>();
        private ShareContext share = new ShareContext();
        private SubmitData submit = new SubmitData();
        private BackgroundWorker worker = new BackgroundWorker();


        public Calc()
        {
            InitializeComponent();

            this.Title = ApplicationStrings.CalcPageTitle;

            this.DataContext = submit;

            worker.WorkerReportsProgress = true;
            worker.DoWork += Worker_DoWork;
            worker.ProgressChanged += Worker_ProgressChanged;
            worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
        }

        // Executes when the user navigates to this page.
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
        }

        // Executes when the user tries to leave this page.
        protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
        {
            foreach (OperationBase operation in this.possiblyPendingOperations)
            {
                if (!operation.IsComplete)
                {
                    if (operation.CanCancel)
                    {
                        operation.Cancel();
                    }
                    else
                    {
                        e.Cancel = true;
                    }
                }
            }
        }

        private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            textResult.Text = String.Format("Input File: {0}\r\nSHA1: {1}\r\nED2K: {2}\r\n\r\n{3}",
                submit.File.Name, submit.SHA1, submit.eMuleHash, submit.GetMuleLink());
            btnBrowse.IsEnabled = true;

            //
            submit.FileSize = submit.File.Length.ToString();
            //

            this.submit.CurrentOperation = this.share.VerifyShip(
                      this.submit,
                      this.SubmitOperation_Completed, null);

            this.possiblyPendingOperations.Add(this.submit.CurrentOperation);
        }


        private void SubmitOperation_Completed(InvokeOperation<Item> operation)
        {
            if (!operation.IsCanceled)
            {
                if (operation.HasError)
                {
                    ErrorWindow.CreateNew(operation.Error);
                    operation.MarkErrorAsHandled();
                }
                else
                {
                    var ship = operation.Value;

                    if (ship == null)
                    {
                        textResult.Text += "\r\n\r\n查无结果，您的文件可能存在潜在风险！";
                    }
                    else
                    {
                        textResult.Text += string.Format("\r\n\r\n您的文件为正版MSDN，请放心使用。\r\n产品名为：{0}\r\n文件名为：{1}",
                            ship.DetailsName, ship.FileName);
                    }
                }
            }
        }


        private void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progVerify.Value = (double)e.UserState;
        }

        private void Worker_DoWork(object sender, DoWorkEventArgs e)
        {
            // 64k has the best performance!
            const int BLOCK_PIECE = 64 * 1024;

            AsyncSHA1 haSHA1 = new AsyncSHA1();
            AsyncED2K haED2K = new AsyncED2K();
            byte[] buffer = new byte[BLOCK_PIECE];

            using (Stream s = submit.File.OpenRead())
            {
                int read = 0;
                int ellapsed = 0;
                do
                {
                    read = s.Read(buffer, 0, BLOCK_PIECE);
                    if (read > 0)
                    {
                        haSHA1.HashCore(buffer, 0, read);
                        haED2K.HashCore(buffer, 0, read);

                        ellapsed += read;
                        // set percentage to userState instead of percentProgress
                        worker.ReportProgress(0, (ellapsed / (double)submit.File.Length * 100));
                    }
                }
                while (read > 0);
            }

            submit.SHA1 = BitConverter.ToString(haSHA1.HashFinal()).Replace("-", "").ToUpper();
            submit.eMuleHash = BitConverter.ToString(haED2K.HashFinal()).Replace("-", "").ToUpper();
        }

        private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Multiselect = false;
            dlg.Filter = "全部文件|*.*";
            if (dlg.ShowDialog().Value)
            {
                submit.File = dlg.File;

                HashCalculate();
            }
        }

        private void HashCalculate()
        {
            inputFile.Text = String.Format("{0} ({1} bytes)", submit.File.Name, submit.File.Length.ToString("0,0"));

            btnBrowse.IsEnabled = false;
            progVerify.Value = 0;

            worker.RunWorkerAsync();
        }

        private void Result_MouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            var tb = sender as TextBlock;
            Clipboard.SetText(tb.Text);
            MessageBox.Show("Text was copied to your clipboard!");
        }

        private void InputFile_Drop(object sender, DragEventArgs e)
        {
            FileInfo[] sources = e.Data.GetData(DataFormats.FileDrop) as FileInfo[];
            if (sources != null && sources.Count() > 0)
            {
                submit.File = sources.First();

                HashCalculate();
            }
        }

    }
}
